package cn.tedu.costservice.service.impl;

import cn.tedu.charging.common.pojo.dto.ChargingProcessDTO;
import cn.tedu.costservice.dao.repository.CostRepository;
import cn.tedu.costservice.dao.repository.CostRuleRedisRepository;
import cn.tedu.costservice.pojo.entity.ChargingData;
import cn.tedu.costservice.pojo.po.CostRulePO;
import cn.tedu.charging.common.pojo.vo.ChargingProcessVO;
import cn.tedu.costservice.service.CostService;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class CostServiceImpl implements CostService {
    /**
     * 查询redis数据库
     */
    @Autowired
    private CostRuleRedisRepository costRuleRedisRepository;
    /**
     * 查询mysql数据库
      */
    @Autowired
    private CostRepository costRepository;
    /**
     * 保存充电历史记录
     */
    private Map<String, ChargingData> chargingDataMap=new HashMap<>();

    @Override
    public ChargingProcessVO calculateFee(ChargingProcessDTO chargingProcessDTO) {
        log.debug("S1-计算电费:{}",chargingProcessDTO);
        String orderNo = chargingProcessDTO.getOrderNo();
        ChargingData chargingData = chargingDataMap.get(orderNo);
        if (chargingData==null){
            chargingData=new ChargingData();
            //添加数据
            chargingData.setOrderNo(orderNo);
            chargingData.setUserId(chargingProcessDTO.getUserId());
            chargingData.setStartTime(LocalDateTime.now());
            //第一次同步充电数据
            log.debug("第一次充电数据:{}",chargingData);
            chargingDataMap.put(orderNo,chargingData);
        }else {
            //不是第一次,更新数据
            BigDecimal lastCost = chargingData.getTotalCost();
            log.debug("不是第一次,获取上次电费:{}",lastCost);
        }
        //获取计费标准
        List<CostRulePO> costRules = getCostRule(chargingProcessDTO.getStationId());
        log.debug("计费标准:{}",costRules);
        //获取当前时间
        LocalDateTime now=LocalDateTime.now();
        int hour = now.getHour();
        for (CostRulePO costRulePO:costRules){
            if (hour>=costRulePO.getStartTime() && hour< costRulePO.getEndTime()){
                BigDecimal powerFee = costRulePO.getPowerFee();
                //设置当前电的单价
                chargingData.setCurrentFee(powerFee);

                //取电量,判断是不是第一次
                if (chargingData.getChargingProcessDTO() == null) {
                    //第一次上传充电进度
                    //获取充电度数
                    float chargingCapacity = chargingProcessDTO.getChargingCapacity();
                    //把 float 类型 充电度数 chargingCapacity  转为 BigDecimal 类型 chargingCapacityBigDecimal
                    BigDecimal chargingCapacityBigDecimal = new BigDecimal(Float.toString(chargingCapacity));
                    //每度电的价格 * 充电度数
                    BigDecimal chargingCost = powerFee.multiply(chargingCapacityBigDecimal);
                    log.debug("当前时间:{},每度电价格是:{}元,充电量:{},总花费:{}",hour,powerFee,chargingCapacity,chargingCost);
                    //设置本次充电费用
                    chargingData.setTotalCost(chargingCost);
                    //更新最后一次充电情况
                    chargingData.setChargingProcessDTO(chargingProcessDTO);
                }else {
                    //获取最近一次充电信息
                    ChargingProcessDTO lastChargingDTO=chargingData.getChargingProcessDTO();
                    //把金额加起来
                    //上传充电的度数
                    Float lastchargingCapacity = lastChargingDTO.getChargingCapacity();
                    //现在充电度数
                    Float nowlastchargingCapacity = chargingProcessDTO.getChargingCapacity();
                    //实际充电度数
                    BigDecimal realChargingCapacity=new BigDecimal(Float.toString(nowlastchargingCapacity-lastchargingCapacity));
                    BigDecimal chargingCost = powerFee.multiply(realChargingCapacity);
                    //记录总电费
                    BigDecimal totalCost = chargingCost.add(chargingData.getTotalCost());
                    log.debug("当前花费:{},电费总和:{}",chargingCost,totalCost);
                    chargingData.setTotalCost(totalCost);
                    //更新最近一次充电
                    chargingData.setChargingProcessDTO(chargingProcessDTO);
                }
            }
        }

        //显示充电时长
        Duration between = Duration.between(chargingData.getStartTime(), LocalDateTime.now());
        long hours = between.toHours();
        long minutes = between.toMinutes();
        long seconds = between.getSeconds();

        ChargingProcessVO chargingProcessVO = getChargingProcessVO(chargingProcessDTO, chargingData, hours, minutes, seconds);
        return chargingProcessVO;
    }

    @NotNull
    private ChargingProcessVO getChargingProcessVO(ChargingProcessDTO chargingProcessDTO, ChargingData chargingData, long hours, long minutes, long seconds) {
        ChargingProcessVO chargingProcessVO=new ChargingProcessVO();
        BeanUtils.copyProperties(chargingProcessDTO,chargingProcessVO);
        chargingProcessVO.setCurrentFee(chargingData.getCurrentFee());
        chargingProcessVO.setTotalCost(chargingData.getTotalCost());
        chargingProcessVO.setHours(hours);
        chargingProcessVO.setMinutes(minutes);
        chargingProcessVO.setSeconds(seconds);
        chargingProcessVO.setTotalCapacity(chargingProcessDTO.getChargingCapacity());
        return chargingProcessVO;
    }

    /**
     * 获取订单花费信息
     * @param orderNo
     * @return
     */
    @Override
    public ChargingProcessVO getInfo(String orderNo) {
        ChargingData chargingData = chargingDataMap.get(orderNo);
        ChargingProcessDTO lastChargingDTO = chargingData.getChargingProcessDTO();
        log.debug("获取之前的订单数据:{}",lastChargingDTO);
        Duration between = Duration.between(chargingData.getStartTime(), LocalDateTime.now());
        long hours = between.toHours();
        long minutes = between.toMinutes();
        long seconds = between.getSeconds();
        return getChargingProcessVO(lastChargingDTO, chargingData, hours, minutes, seconds);

    }


    /**
     * 获取计费标准
     * @param stationId
     * @return
     */
    private List<CostRulePO> getCostRule(Long stationId){
        log.debug("进入查询计费标准的方法");
        List<CostRulePO> costRuleRedisPOs=costRuleRedisRepository.getCostRuleByStationId(stationId);
        log.debug("从redis中获取数据:{}",costRuleRedisPOs);
        if (costRuleRedisPOs==null){
            //redis没有,取mysql查询
            List<CostRulePO> costRulePOs= costRepository.getCostRuleByStationId(stationId);
            log.debug("从数据库获取:{}",costRulePOs);
            if (costRulePOs.size()!=0) {
                //放入redis
                costRuleRedisRepository.saveRule(stationId,costRulePOs);
                return costRulePOs;
            }else {
                log.debug("没有计费标准");
            }
        }
        return costRuleRedisPOs;
    }
}
